package com.gitee.myclouds.admin.web.common.util;

import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.concurrent.TimeUnit;

/**
 * @author Dolen.Wang
 */
@Component
@Slf4j
public class RedisUtil {
    @Autowired
    private RedisTemplate redisTemplate;
    final private Long expire = 300l;
    final private Long expireAt = 5000l;

    @Autowired
    private RedissonClient redissonClient;
    /**
     * 添加分布式锁
     */
    public Boolean distributedLock(final String key){
        redisTemplate.expire(key,expireAt,TimeUnit.MILLISECONDS);
        Boolean execute = (Boolean)redisTemplate.execute((RedisCallback<Boolean>) connection -> {
            Long expireTime= connection.time()+expire;//获取当前时间+有效时间作为value
            //获取锁
            Boolean result = connection.setNX(key.getBytes(), String.valueOf(expireTime).getBytes());
            if(result){//true为获取到锁，false为锁已存在
                return true;
            }else{
                byte[] value=connection.get(key.getBytes());
                if(value!=null&&value.length>0){
                    Long currentTime= connection.time();
                    if(expireTime<currentTime){//比较当前时间和已存在锁的时间，如果大于， 说明锁已失效，允许线程获取新的锁，如果小于，说明线程还持有锁，不允许获取新的锁。
                        byte[] oldValue= connection.getSet(key.getBytes(),String.valueOf(currentTime+expire).getBytes());
                        return Long.valueOf(new String(oldValue))<currentTime;
                    }else{
                        return false;
                    }
                }
                return true;
            }
        });
        return execute;
    }

    /**
     * 释放锁
     * @param key
     */
    public void releaseLock(String key){
        redisTemplate.delete(key);
    }
    public void lock(){
        RLock rLock=redissonClient.getLock("anyLock");
        rLock.lock();
    }
    public void close(){
        RLock rLock=redissonClient.getLock("anyLock");
        rLock.unlock();
    }
}
